/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 * File Name     : roce_bond_register.c
 * Version       : v2.0
 * Created       : 2021/12/7
 * Last Modified : 2022/3/24
 * Description   : The definition of RoCE bond common macros, function prototypes.
 */

#ifndef ROCE_BOND_H
#define ROCE_BOND_H

#include <net/bonding.h>
#include <linux/netdevice.h>

#include "hinic3_bond.h"

#include "roce.h"
#include "roce_qp.h"
#include "roce_cmd.h"

#define ROCE_BOND_MAX_GROUPS 2
#define ROCE_BOND_2_100G_MAX_GROUPS 1
#define ROCE_BOND_4_25G_MAX_GROUPS 2

/* Adding two roce at a time consumes one bit of the array.
 * Currently, a maximum of 33 nodes are supported, and at least 17.
 * To support roce hot swap, the code logic needs to be reconstructed.
 */
#define ROCE_BOND_HCA_NUM 17

#define ROCE_BOND_MAX_PORTS 4
#define ROCE_BOND_MAX_FUNCS 4

#define ROCE_BOND_NO_VLAN_ID 0
#define ROCE_BOND_RSVD_VLAN_ID 4095

#define ROCE_BOND_PORT_ENABLE 1
#define ROCE_BOND_PORT_DISABLE 0

#define ROCE_BOND_ADD_MAC_TBL 1
#define ROCE_BOND_DEL_MAC_TBL 0

#define ROCE_BOND_FWD_ID_TBL_ALL_BITS 32
#define ROCE_BOND_FWD_ID_TBL_PER_BITS 3
#define ROCE_BOND_FWD_ID_TBL_PER_BITS_MASK 0x7

#define ROCE_BOND_MAX_ACX_QP_NUM 32
#define ROCE_BOND_ACX_QP_ENABLE 1
#define ROCE_BOND_ACX_QP_DISABLE 0

enum {
    ROCE_BOND_FUNC_OWN_FLAG = (1 << 0)
};

enum {
    ROCE_BOND_FLAG = (1 << 0)
};

enum {
    ROCE_BOND_WANT_TWO_SLAVES = 2,   /* 2 slaves per bond_dev */
    ROCE_BOND_WANT_THREE_SLAVES = 3, /* 3 slaves per bond_dev */
    ROCE_BOND_WANT_FOUR_SLAVES = 4   /* 4 slaves per bond_dev */
};

enum {
    ROCE_BOND_WANT_TWO_SLAVES_MASK = 0x3,
    ROCE_BOND_WANT_THREE_SLAVES_MASK = 0x7,
    ROCE_BOND_WANT_FOUR_SLAVES_MASK = 0xf
};

enum {
    ROCE_BOND_2_PORT_NUM = 2,
    ROCE_BOND_4_PORT_NUM = 4
};

enum {
    ROCE_BOND_25G_PORT_SPEED = 25,
    ROCE_BOND_100G_PORT_SPEED = 100
};

enum {
    ROCE_BOND_2_FUNC_NUM = 2,
    ROCE_BOND_4_FUNC_NUM = 4
};

enum {
    ROCE_BOND_INVALID_HCA = -1,
    ROCE_BOND_2_100G_HCA = 0,
    ROCE_BOND_4_25G_HCA = 1,
    ROCE_BOND_2_25G_HCA = 2
};

#define SDI_BOND_SUPPORT_ROCE_FUNC_BIT 1
#define SDI_BOND_SUPPORT_ROCE_FUNC_CNT 1
#define SDI_BOND_SLAVES_FUNC_NUM 2

struct roce3_bond_func {
    struct pci_dev *pdev;
    struct net_device *netdev;
    struct hinic3_lld_dev *lld_dev;
    void *hwdev;
    u16 func_id;
    u8 is_own_flags;
    u8 bond_id;
    u8 er_id;
    bool is_ppf;
};

#define roce3_bond_for_each_func(id, start_id, bond_dev)        \
    for ((id) = (start_id); (id) < ROCE_BOND_MAX_FUNCS; (id)++) \
        if (((bond_dev)->func_use_bits & (((u32)1) << (id))) != 0)

struct roce3_bond_tracker {
    /* B300 not support bonding, so use the lint */
    /*lint -e43*/
    enum netdev_lag_tx_type tx_type;
    struct netdev_lag_lower_state_info netdev_state[ROCE_BOND_MAX_PORTS];
    /*lint +e43*/
    bool is_bonded;
};

typedef void (*roce3_bond_service_func)(const char *bond_name, struct bond_attr *attr);

struct roce3_bond_device {
    char name[IFNAMSIZ];
    struct roce3_bond_func bond_func[ROCE_BOND_MAX_FUNCS];
    struct roce3_bond_tracker bond_tracker;
    struct delayed_work bond_work;
    struct notifier_block nb;
    struct roce3_device *rdev;
    u8 hca_id;
    u8 bond_id;
    u8 flags;
    int port_map[ROCE_BOND_MAX_PORTS];
    u8 slave_cnt;
    u8 active_slave_cnt;
    u32 active_slave_mask;
    u8 max_slave_func_id;
    atomic_t next_port;
    u32 func_use_bits;
    int master_dev_idx;
    struct bonding *bond;
    u32 func_tbl_value;
    roce3_bond_service_func service_proc[BOND_POS_MAX];
    u16 bond_attach;
    u16 rec_hinic_bond_id;
    u16 ipsurx_insert;
    struct bond_attr bond_attr;
};

struct roce3_one_hca_info {
    int dev_cnt;
    bool bond_res_has_alloced;
    int max_bond_grps;
    struct roce3_bond_device *bond_dev[ROCE_BOND_MAX_GROUPS];
};

struct roce3_hca_info {
    int hca_cnt;
    int has_func_per_hca;
    int cur_hca_idx;
    int cur_dev_idx;
    struct mutex hca_bond_mutex;
    bool mutex_has_init_flags;
    int prv_hca_type;
    int cur_hca_type;
    bool new_hca;
    bool hca_finish_scan;
    struct roce3_one_hca_info one_hca_info[ROCE_BOND_HCA_NUM];
};

int roce3_bond_register(struct roce3_device *rdev);
void roce3_bond_unregister(struct roce3_device *rdev);
void roce3_bond_remove_all(void);

bool roce3_bond_is_active(struct pci_dev *pdev);
struct roce3_bond_device *roce3_bond_dev_get(struct pci_dev *pdev, bool get_last_func);
struct net_device *roce3_bond_get_netdev(struct roce3_device *rdev);

int roce3_add_bond_real_slave_mac(struct roce3_device *rdev, u8 *mac);
int roce3_add_bond_vlan_slave_mac(struct roce3_device *rdev, u8 *mac, u16 vlan_id);
void roce3_del_bond_real_slave_mac(struct roce3_device *rdev);
void roce3_del_bond_vlan_slave_mac(struct roce3_device *rdev, u8 *mac, u16 vlan_id);

int roce3_bond_is_eth_port_of_netdev(struct roce3_device *rdev, struct net_device *event_ndev);

void roce3_bond_rr_set_flow(struct roce3_device *rdev, struct roce3_qp *rqp, roce_verbs_qp_attr_s *qp_attr);

bool roce3_is_bonded(const struct roce3_bond_device *bond_dev);
int roce3_cfg_port_tbl(struct roce3_bond_device *bond_dev, u8 bond_state);
int roce3_deactivate_bond(struct roce3_bond_device *bond_dev);

void roce3_bond_init_glb_hca_info(void);
void roce3_bond_judge_new_hca(void);
void roce3_bond_hca_mutex_lock(void);
void roce3_bond_hca_mutex_unlock(void);
void roce3_bond_hca_set_func_info(u8 func_nums, u8 func_type);
void roce3_bond_hca_update_info(void);
bool roce3_bond_res_has_alloced(void);

int roce3_bond_event_cfg_rdev(struct hinic3_lld_dev *lld_dev, void *uld_dev, struct roce3_device **rdev);
int roce3_bonded_port_event_report(struct roce3_device *rdev, const struct hinic3_event_info *event);
void roce3_handle_bonded_port_state_event(struct roce3_device *rdev);
void roce3_bond_set_cfg_rdev(struct roce3_device *rdev, bool clear);
int roce3_bond_add(struct roce3_device *rdev);
void roce3_bond_remove(struct roce3_device *rdev);
void roce3_bond_detach(struct roce3_bond_device *bond_dev);
struct roce3_bond_device *roce3_bond_dev_alloc(void);
struct roce3_bond_device *roce3_find_bond_dev_by_bond_name(const char *bond_name);
int roce3_bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr);

void roce3_before_bond_active(const char *bond_name, struct bond_attr *attr);
void roce3_after_bond_active(const char *bond_name, struct bond_attr *attr);
void roce3_before_bond_modify(const char *bond_name, struct bond_attr *attr);
void roce3_after_bond_modify(const char *bond_name, struct bond_attr *attr);
void roce3_before_bond_deactive(const char *bond_name, struct bond_attr *attr);
void roce3_after_bond_deactive(const char *bond_name, struct bond_attr *attr);

void roce3_bond_modify_ipsurx(struct roce3_bond_device *bond_dev, roce3_modify_ipsu_tbl_mac modify_ipsurx);
bool roce3_bond_dev_erid_is_active(const struct roce3_device *rdev, const struct bond_attr *attr);

bool roce3_get_bond_ipsurx_en(void);
void roce3_set_bond_ipsurx_en(bool ipsurx_en);
#endif
